////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                           BailterRay                                       //
//                    Pip Robbins & Zhao Zhang                                //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
class BailterRayPawn extends UTPawn;

var rotator LastRotation;
var vector DodgeDir;
var bool bStarted;
var bool bPreformingDodge;
var eDoubleClickDir OldDoubleClickMove;
var name BootSockets[2];
var ParticleSystem RocketEffect;
var UTEmitter RightRocketEmitter;
var UTEmitter LeftRocketEmitter;
var ParticleSystem RocketSmokeEffect;
var SoundCue RocketBoostSnd;
Var ParticleSystemComponent RightRocketSmoke;
Var ParticleSystemComponent LeftRocketSmoke;
var bool bRocketSmoke;
var float value;


const DODGE_TIME = 0.8;

//Stop you from mini jumping on enemies
function JumpOffPawn(){};

function DropFlag();

// Forces bots to stay at the same Y value
// Stops bots falling off the map or getting off course
// Forces bots to stay at the same Y value
// Stops bots falling off the map or getting off course
function EnforcePawnPosition()
{
    local vector locationFix;
    local BailterRayPlayerController BPC;
    local BailterRayPawn CurrentPawn;

    foreach LocalPlayerControllers(class'BailterRayPlayerController', BPC)
    {
        if(BPC.Pawn.IsHumanControlled())
            break;
    }

    if(BPC != none)
    {
        foreach VisibleActors ( class'BailterRayPawn',  CurrentPawn, 1500)
        {
            if(!CurrentPawn.IsHumanControlled())
            {
                if(CurrentPawn.Location.Y != BPC.yGamePlane)
                {
                    locationFix = CurrentPawn.Location;
                    locationFix.Y = BPC.yGamePlane;
                    CurrentPawn.Move(locationFix - CurrentPawn.Location);
                    CurrentPawn.Velocity.Y = BPC.yGamePlane - CurrentPawn.Location.Y;
                }
                else
                {
                    CurrentPawn.Velocity.Y = 0;
                }
            }
        }
    }
}

//Tick
simulated function Tick(float DeltaTime)
{
    local rotator rot;
    local int deltaPitch;
    local bool bTurned;

    //call previous parent tick function
    super.Tick(DeltaTime);

     //Everything after this is bot only related
    if(UTBot(controller) == None)
         return;

    // Forces bots to stay at the same Y value
    EnforcePawnPosition();

    JumpZ=0; //stops the bots from jumping
   	//gets the current rotation direction stores in rot
   	rot = rotator(Controller.FocalPoint - (Location + vect(0, 0, 1) * HeadOffset));

   	//forces 2d direction of facing forward of backwards
   	if(abs(rot.Yaw) < 16384)
   	    rot.Yaw = 0;
    else
        rot.Yaw = 32768;

    //applies a limit on how much you can change the pitch in one tick
    deltaPitch = RotationRate.Pitch * DeltaTime * 3;

    //Checks to see if you have swapped direction
    if(rot.Yaw == LastRotation.Yaw)
    {
        //checks to see if pitch has been changed more then deltapitch limit
        //If it change is less then our delta limit it will accept the change
        if(abs(rot.Pitch - LastRotation.Pitch) <= deltaPitch)
            LastRotation = rot;
        //Change in pitch is is larger then our delta limit so it only
        //increments by our delta limit. enables smooth limited movement
        else if(rot.Pitch > LastRotation.Pitch) //pitch upwards direction
            LastRotation.Pitch += deltaPitch;
        else //pitch in a downwards direction
            LastRotation.Pitch -= deltaPitch;
    }
    else //Changed Direction since last tick
    {
        if(rot.Pitch >= 0)
            LastRotation.Pitch += deltaPitch; //pitch is going up
        else
            LastRotation.Pitch -= deltaPitch; //pitch is moving downwards
    }

    //If your aimming goes beyond directly vertical
    if(LastRotation.Pitch > 16384)
    {
        // Makes bot face the other direction when aimming upwards
        LastRotation.Pitch = 32768 - LastRotation.Pitch;
        bTurned = true;
    }
    else if(LastRotation.Pitch < -16384)
    {
        //Makes bot face the other direction when aimming down
        LastRotation.Pitch = -32768 - LastRotation.Pitch;
        bTurned = true;
    }

    if(bTurned)
    {
        if(abs(LastRotation.Yaw) < 16384)
            LastRotation.Yaw = 32768;
        else
            LastRotation.Yaw = 0;
    }

    Controller.SetRotation(LastRotation);

    rot = LastRotation;
    SetRemoteViewPitch(rot.Pitch);
    rot.Pitch = 0;
    SetRotation(rot);
}

function bool Dodge(eDoubleClickDir DoubleClickMove)
{
    local vector TraceStart, TraceEnd, HitLocation, HitNormal;
    local Actor HitActor;
    local bool bFalling, out;

    bPreformingDodge = true;

    OldDoubleClickMove = DoubleClickMove;
    if(bIsCrouched || bWantsToCrouch || (Physics != PHYS_Walking && Physics != PHYS_Falling))
        return false;

    if(Physics == PHYS_Falling)
    {
        bFalling = true;

        if(DoubleClickMove == DCLICK_Left)
            TraceEnd = vect(1, 0, 0);
        else if(DoubleClickMove == DCLICK_Right)
            TraceEnd = vect(-1, 0, 0);

        TraceStart = Location - (CylinderComponent.CollisionHeight - 16) * vect(0, 0, 1) + TraceEnd * (CylinderComponent.CollisionRadius - 16);
        TraceEnd = TraceStart + TraceEnd * 40;
        HitActor = Trace(HitLocation, HitNormal, TraceEnd, TraceStart, false, vect(16, 16, 16));

        HitNormal.Y = 0;
        HitNormal = normal(HitNormal);

        if((HitActor == none) || (HitNormal.Z < -0.1))
            return false;
        if(!HitActor.bWorldGeometry)
        {
            if(!HitActor.bBlockActors)
                return false;
            if((Pawn(HitActor) != none) && (Vehicle(HitActor) == none))
                return false;
        }
    }

    if(bFalling)
    {
        Velocity = vect(0, 0, 0);
        Acceleration = vect(0, 0, 0);
    }

    ClearTimer('mydodge');

    out = PerformDodge(DoubleClickMove, DodgeDir, vect(0,0,0));
    setTimer(DODGE_TIME,false,'MyDodge');

    return out;
}

simulated function MyDodge()
{
      PerformDodge(OldDoubleClickMove, -(DodgeDir), vect(0,1,0));
}

function bool PerformDodge(eDoubleClickDir DoubleClickMove, vector Dir, vector Cross)
{
     if (DoubleClickMove == DCLICK_Back || DoubleClickMove == DCLICK_Left || DoubleClickMove == DCLICK_Right || DoubleClickMove == DCLICK_Forward)
         return false;

     super.PerformDodge(DoubleClickMove,Dir,cross);
}

function bool DoJump( bool bUpdating )
{
	local vector SocketLocation;
	local rotator SocketRotation;

    if(CanDoubleJump())
    {
      return super.DoJump(bUpdating);
    }

    if(super.DoJump(bUpdating) == true)
    {
        if(PlayerController(Controller) != None &&  PlayerController(Controller).IsLocalPlayerController())
        {
       	    if(self.Mesh != None)
       	    {
		        if(self.Mesh.GetSocketWorldLocationAndRotation(self.BootSockets[0], SocketLocation, SocketRotation))
		        {

			        RightRocketEmitter = Spawn(class'UTEmitter', self,, SocketLocation, SocketRotation);
			        RightRocketEmitter.SetBase(self,, self.Mesh, self.BootSockets[0]);
			        RightRocketEmitter.SetTemplate(RocketEffect, true);
		            RightRocketEmitter.SetDrawScale(0.6);
                    RightRocketSmoke = WorldInfo.MyEmitterPool.SpawnEmitter(RocketSmokeEffect, SocketLocation, SocketRotation,  RightRocketEmitter);
                    RightRocketSmoke.SetScale(0.6);

		        }
		        if(self.Mesh.GetSocketWorldLocationAndRotation(self.BootSockets[1], SocketLocation, SocketRotation))
		        {
			        LeftRocketEmitter = Spawn(class'UTEmitter', self,, SocketLocation, SocketRotation);
			        LeftRocketEmitter.SetBase(self,, self.Mesh, self.BootSockets[1]);
			        LeftRocketEmitter.SetTemplate(RocketEffect, true);
			        LeftRocketEmitter.SetDrawScale(0.6);
                    LeftRocketSmoke = WorldInfo.MyEmitterPool.SpawnEmitter(RocketSmokeEffect, SocketLocation, SocketRotation,  LeftRocketEmitter);
                    LeftRocketSmoke.SetScale(0.6);
		        }
		        bRocketSmoke = true;
		        SetTimer(0.5, true, 'RocketSmokeTrail');
            }
        }

        return true;
    }

    return false;

}

function DoDoubleJump( bool bUpdating )
{
	super.DoDoubleJump(bUpdating);

    if(PlayerController(Controller) != None &&  PlayerController(Controller).IsLocalPlayerController())
    {

       RightRocketEmitter.PlaySound(RocketBoostSnd, false, true, false);

       RightRocketEmitter.SetDrawScale(0.9);
       LeftRocketEmitter.SetDrawScale(0.9);
       SetTimer(0.4, false, 'FirstPowerRocket');

    }
}

function RocketSmokeTrail()
{
    local vector SocketLocation;
	local rotator SocketRotation;

    if(!bRocketSmoke)
    {
        ClearTimer('RocketSmokeTrail');
        return;
    }

    if(Mesh.GetSocketWorldLocationAndRotation(self.BootSockets[0], SocketLocation, SocketRotation))
    {
	    RightRocketSmoke = WorldInfo.MyEmitterPool.SpawnEmitter(RocketSmokeEffect, SocketLocation, SocketRotation,  RightRocketEmitter);
        RightRocketSmoke.SetScale(0.6);
    }
    if(Mesh.GetSocketWorldLocationAndRotation(self.BootSockets[1], SocketLocation, SocketRotation))
    {
        LeftRocketSmoke = WorldInfo.MyEmitterPool.SpawnEmitter(RocketSmokeEffect, SocketLocation, SocketRotation,  LeftRocketEmitter);
        LeftRocketSmoke.SetScale(0.6);
    }
}

function FirstPowerRocket()
{
    RightRocketEmitter.SetDrawScale(0.6);
    LeftRocketEmitter.SetDrawScale(0.6);
    SetTimer(0.4, false, 'SecondPowerRocket');
}

function SecondPowerRocket()
{
    RightRocketEmitter.SetDrawScale(0.4);
    LeftRocketEmitter.SetDrawScale(0.4);
}

event Landed(vector HitNormal, actor FloorActor)
{
    Super.Landed(HitNormal, FloorActor);
    RightRocketEmitter.Destroy();
    LeftRocketEmitter.Destroy();
    bRocketSmoke = false;
    RightRocketSmoke.SetActive(false);
    LeftRocketSmoke.SetActive(false);
}

simulated event Destroyed()
{
    RightRocketEmitter.Destroy();
    LeftRocketEmitter.Destroy();
    bRocketSmoke = false;
    RightRocketSmoke.SetActive(false);
    LeftRocketSmoke.SetActive(false);
}

function NotifySpree(UTPlayerReplicationInfo Other, int num)
{
    // do nothing!
}

function EndSpree(UTPlayerReplicationInfo Killer, UTPlayerReplicationInfo Other)
{
    // do nothing!
}

function PlayTeleportEffect(bool bOut, bool bSound)
{
	local int TeamNum, TransCamIndx;
	local UTPlayerController PC;
	local BailterRayKey Key;

	if ( (PlayerReplicationInfo != None) && (PlayerReplicationInfo.Team != None) )
	{
		TeamNum = PlayerReplicationInfo.Team.TeamIndex;
	}
	if ( !bSpawnIn && (WorldInfo.TimeSeconds - SpawnTime < UTGame(WorldInfo.Game).SpawnProtectionTime) )
	{
		bSpawnIn = true;
		SetBodyMatColor( SpawnProtectionColor, UTGame(WorldInfo.Game).SpawnProtectionTime );
		SpawnTransEffect(TeamNum);
		if (bSound)
		{
			PlaySound(SpawnSound);
		}
	}
	else
	{

	    PC = UTPlayerController(Controller);
	    foreach AllActors(class'BailterRayKey', Key)
	    {

	       if(Key.FirstTouch != none)
               Key.SetHolder(PC);
	    }

		SetBodyMatColor( TranslocateColor[TeamNum], 1.0 );
		SpawnTransEffect(TeamNum);
		if (bSound)
		{
			PlaySound(TeleportSound);
		}
	}

	if (bOut)
	{
		PC = UTPlayerController(Controller);
		if (PC != None)
		{
			if ( !WorldInfo.Game.bTeamGame || PlayerReplicationInfo == None || PlayerReplicationInfo.Team == None
				|| PlayerReplicationInfo.Team.TeamIndex > 1 )
			{
				TransCamIndx = 2;
			}
			else
			{
				TransCamIndx = TeamNum;
			}
			PC.ClientPlayCameraAnim(TransCameraAnim[TransCamIndx], 1.0f);
		}
	}
	MakeNoise(1.0);
}


defaultproperties
{
    // Rocket Boots Related Stuff
    BootSockets(0)="RightRocketBoot"
    BootSockets(1)="LeftRocketBoot"
    RocketEffect=ParticleSystem'AstroExplorer.Effects.Boot_Flame'
    RocketSmokeEffect=ParticleSystem'AstroExplorer.Effects.Smoke_Trail'
    RocketBoostSnd=SoundCue'A_Pickups_Powerups.Powerups.A_Powerup_JumpBoots_JumpCue'

    // Important Tweaking Values
    Health = 100
    DamageScaling = 1.0
    MaxMultiJump = 1
    MultiJumpRemaining = 1
    MultiJumpBoost = 0
    MaxDoubleJumpHeight=260.000000
    DoubleJumpThreshold=800.000000
    FallSpeedThreshold=125.000000
    CustomGravityScaling=1.000000
    MaxJumpHeight=250.000000
    CrouchHeight=29.000000
    GroundSpeed=300.000000
    AirSpeed=200.000000
    MaxFallSpeed=1000.000000  //Before Taking Damage
    SpawnProtectionColor=(R=40.000000,G=40.000000,B=0.000000,A=1.000000)
    JumpZ = 550.0
    bCanRagDoll=False
    DodgeSpeed = 380.0
    DodgeSpeedZ = 200.0
    DodgeDir = (X =0.0, Y = -1.0, Z = 0.0)
    bPreformingDodge = false
    bStarted = false

    DefaultFamily=class'BailterRay.BailterRay_FamilyInfo_EvilRobot'
    DefaultMesh=SkeletalMesh'EvilRobot.EvilRobotSkel'
    SpawnSound=SoundCue'BailterRaySoundPackages.SpawnSound1Cue' //Spawn Sound
    TeleportSound=SoundCue'BailterRaySoundPackages.SpawnSound1Cue'
}